OutlineSettings.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. using System;
  2. using ExternPropertyAttributes;
  3. using UnityEngine;
  4. using UnityEngine.Rendering.Universal;
  5. using Debug = UnityEngine.Debug;
  6. // ReSharper disable RedundantDefaultMemberInitializer
  7. #if UNITY_2022_3_OR_NEWER
  8. namespace FlatKit {
  9. [CreateAssetMenu(fileName = "OutlineSettings", menuName = "FlatKit/Outline Settings")]
  10. public class OutlineSettings : ScriptableObject {
  11. [Space] // Expandable.
  12. [Tooltip("The color of the lines. Alpha is used for transparency, " +
  13. "0 means fully transparent and 1 means fully opaque lines.")]
  14. public Color edgeColor = Color.white;
  15. [Range(0, 5)]
  16. [Tooltip("The width of the lines in screen space. If 'Resolution Invariant' is disabled, " +
  17. "this is the width in pixels. Otherwise, it is a relative width.")]
  18. public int thickness = 1;
  19. [Tooltip("If enabled, the line width will stay constant regardless of the rendering resolution. " +
  20. "However, some of the lines may appear blurry.")]
  21. public bool resolutionInvariant = false;
  22. [Tooltip("If enabled, the outline will become more transparent the further away it is from the camera.")]
  23. public bool fadeWithDistance = false;
  24. [ShowIf(nameof(fadeWithDistance))]
  25. [Label(" Start")]
  26. [Tooltip("The distance from the camera at which the outline starts to fade. The value is in world units.")]
  27. public float fadeRangeStart = 10f;
  28. [ShowIf(nameof(fadeWithDistance))]
  29. [Label(" End")]
  30. [Tooltip("The distance from the camera at which the outline is fully transparent. The value is in world units.")]
  31. public float fadeRangeEnd = 50f;
  32. [HorizontalLine]
  33. [Tooltip("Whether to use depth information to draw outlines. This adds lines around objects that are in front of " +
  34. "other objects.")]
  35. public bool useDepth = true;
  36. [ShowIf(nameof(useDepth))]
  37. [Label(" Min Threshold")]
  38. [Min(0)]
  39. [Tooltip("Minimum distance between two pixels to be considered an edge. The outline is drawn almost transparent.")]
  40. public float minDepthThreshold = 0.1f;
  41. [ShowIf(nameof(useDepth))]
  42. [Label(" Max Threshold")]
  43. [Min(0)]
  44. [Tooltip("Maximum distance between two pixels to be considered an edge. The outline is drawn fully opaque.")]
  45. public float maxDepthThreshold = 0.25f;
  46. [HorizontalLine(1, EColor.Translucent)]
  47. [Tooltip("Whether to use world-space normals information to draw outlines. This adds lines " +
  48. "on sharp edges of objects.")]
  49. public bool useNormals = false;
  50. [ShowIf(nameof(useNormals))]
  51. [Label(" Min Threshold")]
  52. [Min(0)]
  53. [Tooltip("Minimum angle between two normals to be considered an edge. The outline is drawn almost transparent.")]
  54. public float minNormalsThreshold = 0.1f;
  55. [ShowIf(nameof(useNormals))]
  56. [Label(" Max Threshold")]
  57. [Min(0)]
  58. [Tooltip("Maximum angle between two normals to be considered an edge. The outline is drawn fully opaque.")]
  59. public float maxNormalsThreshold = 0.25f;
  60. [HorizontalLine(1, EColor.Translucent)]
  61. [Tooltip("Whether to use color information to draw outlines. This adds lines where the color of the object " +
  62. "changes.")]
  63. public bool useColor = false;
  64. [ShowIf(nameof(useColor))]
  65. [Label(" Min Threshold")]
  66. [Min(0)]
  67. [Tooltip("Minimum difference in color between two pixels to be considered an edge. The outline is drawn almost " +
  68. "transparent.")]
  69. public float minColorThreshold = 0.1f;
  70. [ShowIf(nameof(useColor))]
  71. [Label(" Max Threshold")]
  72. [Min(0)]
  73. [Tooltip("Maximum difference in color between two pixels to be considered an edge. The outline is drawn fully " +
  74. "opaque.")]
  75. public float maxColorThreshold = 0.25f;
  76. [HorizontalLine]
  77. [Tooltip("The render stage at which the effect is applied. To exclude transparent objects, like water or UI " +
  78. "elements, set this to \"Before Transparent\".")]
  79. public RenderPassEvent renderEvent = RenderPassEvent.BeforeRenderingPostProcessing;
  80. [Tooltip("Only draw the outline, replacing the original color with a complimentary color.")]
  81. public bool outlineOnly = false;
  82. [Tooltip("Whether the effect should be applied in the Scene view as well as in the Game view. Please keep in " +
  83. "mind that Unity always renders the scene view with the default Renderer settings of the URP config.")]
  84. public bool applyInSceneView = true;
  85. [HideInInspector]
  86. public Material effectMaterial;
  87. internal Action onSettingsChanged;
  88. internal Action onReset;
  89. private void OnValidate() {
  90. if (minDepthThreshold > maxDepthThreshold + float.Epsilon) {
  91. Debug.LogWarning("<b>[Flat Kit]</b> Outline configuration error: <b>'Min Depth Threshold'</b> must not " +
  92. "be greater than <b>'Max Depth Threshold'</b>");
  93. }
  94. if (minNormalsThreshold > maxNormalsThreshold + float.Epsilon) {
  95. Debug.LogWarning("<b>[Flat Kit]</b> Outline configuration error: <b>'Min Normals Threshold'</b> must not " +
  96. "be greater than <b>'Max Normals Threshold'</b>");
  97. }
  98. if (minColorThreshold > maxColorThreshold + float.Epsilon) {
  99. Debug.LogWarning("<b>[Flat Kit]</b> Outline configuration error: <b>'Min Color Threshold'</b> must not " +
  100. "be greater than <b>'Max Color Threshold'</b>");
  101. }
  102. fadeRangeStart = Mathf.Max(0f, Mathf.Min(fadeRangeStart, fadeRangeEnd));
  103. fadeRangeEnd = Mathf.Max(fadeRangeStart, Mathf.Min(fadeRangeEnd, 1000f));
  104. onSettingsChanged?.Invoke();
  105. }
  106. private void Reset() {
  107. onReset?.Invoke();
  108. }
  109. private void OnDestroy() {
  110. onSettingsChanged = null;
  111. onReset = null;
  112. }
  113. }
  114. }
  115. #else
  116. namespace FlatKit {
  117. [CreateAssetMenu(fileName = "OutlineSettings", menuName = "FlatKit/Outline Settings")]
  118. public class OutlineSettings : ScriptableObject {
  119. public Color edgeColor = Color.white;
  120. [Range(0, 5)]
  121. public int thickness = 1;
  122. [Tooltip("If enabled, the line width will stay constant regardless of the rendering resolution. " +
  123. "However, some of the lines may appear blurry.")]
  124. public bool resolutionInvariant = false;
  125. [Space]
  126. public bool useDepth = true;
  127. public bool useNormals = false;
  128. public bool useColor = false;
  129. [Header("Advanced settings")]
  130. public float minDepthThreshold = 0f;
  131. public float maxDepthThreshold = 0.25f;
  132. [Space]
  133. public float minNormalsThreshold = 0f;
  134. public float maxNormalsThreshold = 0.25f;
  135. [Space]
  136. public float minColorThreshold = 0f;
  137. public float maxColorThreshold = 0.25f;
  138. [Space, Tooltip("The render stage at which the effect is applied. To exclude transparent objects, " +
  139. "like water or UI elements, set this to \"Before Transparent\".")]
  140. public RenderPassEvent renderEvent = RenderPassEvent.BeforeRenderingPostProcessing;
  141. public bool outlineOnly = false;
  142. [Tooltip("Whether the effect should be applied in the Scene view as well as in the Game view. Please keep in " +
  143. "mind that Unity always renders the scene view with the default Renderer settings of the URP config.")]
  144. public bool applyInSceneView = true;
  145. private void OnValidate() {
  146. if (minDepthThreshold > maxDepthThreshold + float.Epsilon) {
  147. Debug.LogWarning("<b>[Flat Kit]</b> Outline configuration error: 'Min Depth Threshold' must not " +
  148. "be greater than 'Max Depth Threshold'");
  149. }
  150. if (minNormalsThreshold > maxNormalsThreshold + float.Epsilon) {
  151. Debug.LogWarning("<b>[Flat Kit]</b> Outline configuration error: 'Min Normals Threshold' must not " +
  152. "be greater than 'Max Normals Threshold'");
  153. }
  154. if (minColorThreshold > maxColorThreshold + float.Epsilon) {
  155. Debug.LogWarning("<b>[Flat Kit]</b> Outline configuration error: 'Min Color Threshold' must not " +
  156. "be greater than 'Max Color Threshold'");
  157. }
  158. }
  159. }
  160. }
  161. #endif